package opensocial.apps.treat.events
{
  import com.adobe.serialization.json.JSON;
  
  import flash.events.EventDispatcher;
  
  import mx.collections.ArrayCollection;
  import mx.controls.Alert;
  
  import opensocial.apps.treat.model.Constants;
  import opensocial.apps.treat.model.Invitation;
  import opensocial.apps.treat.model.Place;
  import opensocial.apps.treat.model.User;
  import opensocial.apps.treat.model.Utils;
  
  import org.opensocial.client.base.Collection;
  import org.opensocial.client.base.DataRequest;
  import org.opensocial.client.base.GadgetsIo;
  import org.opensocial.client.base.Person;
  import org.opensocial.client.core.Feature;
  import org.opensocial.client.features.AsyncDataRequest;
  import org.opensocial.client.features.PeopleRequestOptions;
  import org.opensocial.client.features.ProxiedRequest;
  import org.opensocial.client.features.ProxiedRequestEvent;
  import org.opensocial.client.features.ProxiedRequestOptions;
  import org.opensocial.client.features.ResponseItemEvent;
  import org.opensocial.client.jswrapper.JsWrapperClient;
  
  public class TreatDataRequest extends EventDispatcher {
    
    private static const MODE_GET_MASTER:int = 1;    
    private static const MODE_GET_REGISTER:int = 2;  
    private static const MODE_GET_FRIENDS:int = 3;  
    private static const MODE_GET_PLACE:int = 4;  
    private static const MODE_GET_INVITATION:int = 5;  
    
    private var result:Result = null;
    private var client:JsWrapperClient;
    private var mode:int;
    public var master:User;
    public var friends:ArrayCollection;
    private var friendSize:Number;
    public var noFriends:ArrayCollection;   
    public var places:ArrayCollection;
    public var invitations:ArrayCollection;
    

    public function TreatDataRequest() {
      client = new JsWrapperClient("opensocial.flash");
      client.start();
    }
    
    public function getMaster(result:Result):void {
      if (client.ready) { 
        mode = MODE_GET_MASTER;        
        this.result = result;
        var req:AsyncDataRequest = new AsyncDataRequest(
            Feature.PEOPLE_GET,
            new PeopleRequestOptions()
                .setUserId("@me")
                .setGroupId("@self"));
        req.addEventListener(ResponseItemEvent.COMPLETE, getMasterFromOpenSocialResultCallback);
        req.addEventListener(ResponseItemEvent.ERROR, getMasterFromOpenSocialFaultCallback);
        req.send(client);        
      } else {
        result.faultCallback('OpneSocial Client SDK has an error.');  
      }
    }

    private function getMasterFromOpenSocialFaultCallback(event:ResponseItemEvent):void {
      result.faultCallback(event.response.getErrorMessage());
    }

    private function getMasterFromOpenSocialResultCallback(event:ResponseItemEvent):void {
      var p:Person = event.response.getData();
      master = new User(p.getId(), p.getDisplayName(), p.getThumbnailUrl());
      getUserFromBackEnd(master);
    }
    
    private function getUserFromBackEnd(user:User):void {
      var apiURL:String = Constants.API_GET_PLAYER + "vid=" + user.id + "&oid=" + master.id + "&ts=" + (new Date).getTime();
      var req:ProxiedRequest = new ProxiedRequest(apiURL,
          new ProxiedRequestOptions()
              .setContentType(GadgetsIo.ContentType.TEXT));
      switch (mode) {
        case MODE_GET_MASTER: 
          req.addEventListener(ProxiedRequestEvent.COMPLETE, getMasterFormBackEndResultCallback);
          break;
        case MODE_GET_FRIENDS: 
          req.addEventListener(ProxiedRequestEvent.COMPLETE, getFriendFromBackEndResultCallback);
          break;          
      }      
      req.addEventListener(ProxiedRequestEvent.ERROR, makeRequestEventErrorHandler);
      req.send(client);
    }    

    private function getMasterFormBackEndResultCallback(event:ProxiedRequestEvent):void {      
      var o:Object = JSON.decode(event.response.getData());
      if (o.hasError) {
        if (o.message.messageId == 'player_not_found') {
          mode = MODE_GET_REGISTER;
          registerUser();
        } else {
          result.faultCallback(o.error.messageId);
        }      
      } else if (o.player) {
        master.level = Constants.LEVELS[o.player.level];
        master.money = o.player.cash;
        master.popularity = o.player.popular; 
        master.theme = o.player.backgroud;  
        result.resultCallback(master);
      }
    }
 
    private function registerUser():void {      
      var apiURL:String = Constants.BACKEND_URL_BASE;
      var postData:Object = new Object();
      postData.cmd = "init";
      postData.ctn = "default";
      postData.vid = master.id;
      postData.oid = master.id;
      postData.name = master.name;
      postData.photo = master.photoPath;
      postData.ts = (new Date).getTime();
      var req:ProxiedRequest = new ProxiedRequest(apiURL,
          new ProxiedRequestOptions()
              .setContentType(GadgetsIo.ContentType.TEXT).setMethod(GadgetsIo.MethodType.POST).setPostData(postData));
      req.addEventListener(ProxiedRequestEvent.COMPLETE, getRegisterUserFormBackEndResultCallback);
      req.addEventListener(ProxiedRequestEvent.ERROR, makeRequestEventErrorHandler);
      req.send(client);
    }

    private function getRegisterUserFormBackEndResultCallback(event:ProxiedRequestEvent):void {
      var o:Object = JSON.decode(event.response.getData());
      if (o.hasError) {
          result.faultCallback(o.error.messageId);
      } else if (o.player) {
        var player:User = new User(o.player.id, o.player.name, o.player.photoUrl);
        player.level = Constants.LEVELS[o.player.level];
        player.money = o.player.cash;
        player.popularity = o.player.popular; 
        player.theme = o.player.backgroud;      
        result.resultCallback(player);
      }
    }
    
    private function makeRequestEventErrorHandler(event:ProxiedRequestEvent):void {
      if (mode == MODE_GET_FRIENDS) {
        friends.addItem(null);
      } else {
        result.faultCallback(event.response.getText());
      }
    }   

    public function getFriends(result:Result):void {
      if (client.ready) { 
        this.result = result;        
        mode = MODE_GET_FRIENDS;
        var req:AsyncDataRequest = new AsyncDataRequest(
            Feature.PEOPLE_GET,
            new PeopleRequestOptions()
                .setUserId("@me")
                .setGroupId("@friends").setFilterBy(DataRequest.FilterType.HAS_APP));
        req.addEventListener(ResponseItemEvent.COMPLETE, getFriendsFromOpenSocialResultCallback);
        req.addEventListener(ResponseItemEvent.ERROR, getFriendsFromOpenSocialFaultCallback);           
        req.send(client);     
      } else {
        result.faultCallback('OpneSocial Client SDK has an error.');
      }
    }
    
    private function getFriendsFromOpenSocialFaultCallback(event:ResponseItemEvent):void { 
      if (mode != MODE_GET_FRIENDS)
        result.faultCallback(event.response.getErrorMessage());
    }
    
    private function getFriendsFromOpenSocialResultCallback(event:ResponseItemEvent):void {
      var c:Collection = event.response.getData();
      var people:Array = c.getArray();
      friends = new ArrayCollection();
      friendSize = people.length;
      for each (var p:Person in people) {
        var user:User = new User(p.getId(), p.getDisplayName(), p.getThumbnailUrl());
        getUserFromBackEnd(user);
      } 
      if (people.length == 0) {
        result.resultCallback(null);
      }    
    }
    
    private function getFriendFromBackEndResultCallback(event:ProxiedRequestEvent):void {
      var o:Object = JSON.decode(event.response.getData());
      if (o.hasError) {
        friends.addItem(null);
          //result.faultCallback(o.error.messageId);
      } else if (o.player) {
        var player:User = new User(o.player.id, o.player.name, o.player.photoUrl);
        player.level = Constants.LEVELS[o.player.level];
        player.money = o.player.cash;
        player.popularity = o.player.popular; 
        player.theme = o.player.backgroud;         
        friends.addItem(player);  
      }
      if (friendSize == friends.length) {
        var users:ArrayCollection = new ArrayCollection();
        for each (var f:User in friends) {
          if (f != null) {
            users.addItem(f);
          }
        }
        result.resultCallback(users);
      }
    }
    
    public function getPlaces(result:Result):void {
      this.result = result;    
      mode = MODE_GET_PLACE; 
      var apiURL:String = Constants.API_GET_PLACE + "vid=" + master.id + "&oid=" + master.id;     
      var req:ProxiedRequest = new ProxiedRequest(apiURL + "&ts=" + (new Date).getTime(),
          new ProxiedRequestOptions()
              .setContentType(GadgetsIo.ContentType.TEXT));
      req.addEventListener(ProxiedRequestEvent.COMPLETE, getPlacesResultCallback);
      req.addEventListener(ProxiedRequestEvent.ERROR, makeRequestEventErrorHandler);
      req.send(client);
    }
    
    private function getPlacesResultCallback(event:ProxiedRequestEvent):void {
      var o:Object = JSON.decode(event.response.getData());
      var theme:Number = Math.round(Math.random() * 8) + 1;
      if (o.hasError) {
//        result.faultCallback(o.error.messageId);
//      } else if (o.data.id) {
//        var place:Place = new Place(o.data.id, o.data.name, Constants.WWW_URL_BASE + 'logo_' + o.data.id + '.png', o.data.stay, theme, o.data.price);
//        result.resultCallback(place);
      } else if (o.data) {
        places = new ArrayCollection();
        for each (var obj:Object in o.data) {
          var p:Place = new Place(obj.id, obj.name, Constants.WWW_URL_BASE + 'logo_' + obj.id + '.png', obj.stay, theme, obj.price);
          places.addItem(p);
          theme = Math.round(Math.random() * 8) + 1;
        }
        result.resultCallback(places);
      }      
    }    
    
    public function createInvitation(result:Result, invitation:Invitation):void {
      if (invitation && invitation.guests) {
        this.result = result;     
        var guests:Array = new Array();
        for each (var guest:User in invitation.guests) {
          guests.push(guest.id);
        }
        var apiURL:String = Constants.BACKEND_URL_BASE;
        var postData:Object = new Object();
        postData.cmd = "invite";
        postData.ctn = "default";
        postData.vid = master.id;
        postData.oid = master.id;
        postData.guests = guests.join(',');
        postData.date = dateToString(invitation.startTime);
        
        postData.place = invitation.place.id;
        postData.ts = (new Date).getTime();
        
        var req:ProxiedRequest = new ProxiedRequest(apiURL,
            new ProxiedRequestOptions()
                .setContentType(GadgetsIo.ContentType.TEXT).setMethod(GadgetsIo.MethodType.POST).setPostData(postData));
        req.addEventListener(ProxiedRequestEvent.COMPLETE, createInvitationResultCallback);
        req.addEventListener(ProxiedRequestEvent.ERROR, makeRequestEventErrorHandler);
        req.send(client);             
      } 
    }    
 
    private function createInvitationResultCallback(event:ProxiedRequestEvent):void {
      var o:Object = JSON.decode(event.response.getData());
      if (o.hasError) {
        result.faultCallback(o.error.messageId);
      } else {
        result.resultCallback(null);
      }
    } 
    
    private function dateToString(date: Date): String {
    	var _date:Date = new Date(date.getTime());
    	var arr: Array = [];
    	arr.push(_date.getFullYear() + '/');
    	arr.push(_date.getMonth() + '/');
    	arr.push(_date.getDate() + ' ');
     	arr.push(_date.getHours() + ':');
     	arr.push(_date.getMinutes());
     	return arr.join('');
    }
    
    
    public function getInvitations(result:Result, user:User = null):void {
      this.result = result;    
      mode = MODE_GET_INVITATION; 
      var apiURL:String = Constants.API_GET_INVITES + "oid=" + master.id + "&vid=";   
      if (user) {
        apiURL += user.id;
      } else {
        apiURL += master.id;
      }
      
      var req:ProxiedRequest = new ProxiedRequest(apiURL + "&ts=" + (new Date).getTime(),
          new ProxiedRequestOptions()
              .setContentType(GadgetsIo.ContentType.TEXT));
      req.addEventListener(ProxiedRequestEvent.COMPLETE, getInvitationsResultCallback);
      req.addEventListener(ProxiedRequestEvent.ERROR, makeRequestEventErrorHandler);
      req.send(client);      
    }
    
    private function getInvitationsResultCallback(event:ProxiedRequestEvent):void {
      var o:Object = JSON.decode(event.response.getData());
      if (o.hasError) {
        result.faultCallback(o.error.messageId);
      } else if (o.host) {
        invitations = new ArrayCollection();
        for each (var obj:Object in o.host) {
          var i:Invitation = new Invitation(master, obj.id);
          i.startTime = new Date(obj.begin);          
          i.place = Utils.getPlaceById(obj.placeid);
          var u:User
          
          if (obj.accepter) {
            for each(var a:Object in obj.accepter) {
              u = Utils.getFriendById(a.id);
              if (!u) {
                u = new User(a.id, a.name);
              }
              i.accept.addItem(u);
            }             
          }

          if (obj.refuser) {
            for each(var r:Object in obj.refuser) {
              u = Utils.getFriendById(r.id);
              if (!u) {
                u = new User(r.id, r.name);
              }
              i.declined.addItem(u);
            }             
          }    

          for each(var g:Object in obj.guests) {
            u = Utils.getFriendById(g.id);
            if (!u) {
              u = new User(g.id, g.name);
            }
            if (Utils.getInstance(g.id, i.accept) == null && Utils.getInstance(g.id, i.declined) == null) {
              i.unresponsive.addItem(u);
            }            
            i.guests.addItem(u);
          }          

          invitations.addItem(i);
        }
        result.resultCallback(invitations);
      }      
    }   
     
  }
}